package com.easy.mongodb.core.toolkit;

import com.easy.mongodb.common.exception.EasyMongoDBException;
import com.easy.mongodb.common.utils.ClassUtils;

import java.io.*;

/**
 * ProductName: easy-mongodb
 * Package: com.easy.mongodb.core.toolkit
 * Description:
 * Author: vapeshop
 * Date: 2022/7/19 10:55
 * UpdateUser: vapeshop
 * UpdateDate: 2022/7/19 10:55
 * UpdateRemark: The modified content
 * Version: 1.0.0
 * <p>
 * Copyright © 2022 vapeshop Technologies Inc. All Rights Reserved
 **/
public class SerializedLambda implements Serializable {
    private static final long serialVersionUID = 8025925345765570181L;

    private Class<?> capturingClass;
    private String functionalInterfaceClass;
    private String functionalInterfaceMethodName;
    private String functionalInterfaceMethodSignature;
    private String implClass;
    private String implMethodName;
    private String implMethodSignature;
    private int implMethodKind;
    private String instantiatedMethodType;
    private Object[] capturedArgs;

    public static SerializedLambda extract(Serializable serializable) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(serializable);
            oos.flush();
            try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())) {
                @Override
                protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
                    Class<?> clazz = super.resolveClass(desc);
                    return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
                }

            }) {
                return (SerializedLambda) ois.readObject();
            }
        } catch (IOException | ClassNotFoundException e) {
            throw new EasyMongoDBException(e);
        }
    }

    public String getInstantiatedMethodType() {
        return this.instantiatedMethodType;
    }

    public Class<?> getInstantiatedClass() {
        String instantiatedMethodType = this.getInstantiatedMethodType();
        String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(";")).replace("/", ".");
        return ClassUtils.toClassConfident(instantiatedType, this.getCapturingClass().getClassLoader());
    }

    public Class<?> getCapturingClass() {
        return this.capturingClass;
    }

    public String getImplMethodName() {
        return this.implMethodName;
    }
}
